/*
 * BlockBitMap.cpp
 *
 *  Created on: Nov 3, 2013
 *      Author: SG0214746
 */

#include "BlockBitMap.h"
#include "../../log/Logger.h"
#include "../../utils/Utils.h"
#include <cmath>

BlockBitMap::BlockBitMap() {
	bitmap.push_back(true);
}

BlockBitMap::~BlockBitMap() {
}

void BlockBitMap::free(BigInt block) {
	bitmap[block] = true;
	save();
}

BigInt BlockBitMap::getFreeBlock() {
	BigInt pos = 0;
	for (std::vector<bool>::iterator it = bitmap.begin(); it != bitmap.end(); ++it, ++pos) {
		if (*it == true) {
			Logger::getInstance().debug("BlockBitMap: Encontrado el bloque " + Utils::toString(bitmap.size() - 1) + " libre");
			return pos;
		}
	}
	bitmap.push_back(true);
	save();
	Logger::getInstance().debug("BlockBitMap: Agregado el bloque " + Utils::toString(bitmap.size() - 1));
	return bitmap.size() - 1;
}

void BlockBitMap::take(BigInt block) {
	bitmap[block] = false;
	save();
}

String BlockBitMap::toString() const {
	String aux;
	for (std::vector<bool>::const_iterator it = bitmap.begin(); it != bitmap.end(); ++it) {
		aux += (*it == true) ? "[1]" : "[0]";
	}
	return aux;
}

void BlockBitMap::save() {
	getDescriptor().seekp(0, std::fstream::beg);
	BigInt bitCount = bitmap.size();
	getDescriptor().write((char*)&bitCount, sizeof(BigInt));
	Binary bytes(std::ceil(((float)bitmap.size()) / 8));
	BigInt bit;
	for(BigInt bitIndex = 0; bitIndex < bitCount; ++bitIndex) {
	   bit = bitmap[bitIndex];
	   bytes[bitIndex/8] |= bit << bitIndex%8;
	}
	getDescriptor().write((char*)&bytes[0], bytes.size());
}

void BlockBitMap::load() {
	getDescriptor().seekg(0, std::fstream::end);
	//BigInt bytesSize = getDescriptor().tellg() - sizeof(BigInt);
	BigInt filePos = getDescriptor().tellg();
	BigInt bytesSize = filePos - sizeof(BigInt);
	getDescriptor().seekg(0, std::fstream::beg);
	BigInt bitmapSize;
	getDescriptor().read((char*)&bitmapSize, sizeof(BigInt));
	bitmap.resize(bitmapSize);
	Binary bytes(bytesSize);
	//getDescriptor().read((char*)bytes.data(), bytes.size());
	getDescriptor().read((char*)&bytes[0], bytes.size());
	bool bit;
	for (BigInt bitPos = 0; bitPos < bitmapSize; bitPos++) {
		bit = bytes[bitPos/8] & (1 << bitPos % 8);
		bitmap[bitPos] = bit;
	}
}
